package com.lvhr.rpc.serializer;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.lvhr.rpc.model.RpcRequest;
import com.lvhr.rpc.model.RpcResponse;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 增强版Jackson序列化器（支持泛型、Java8时间类型、类型擦除处理）
 */
public class JacksonSerializer implements Serializer {

    // 线程安全的ObjectMapper（避免重复创建）
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    // 类型缓存提升性能（特别是泛型类型）
    private static final ConcurrentHashMap<Type, JavaType> TYPE_CACHE = new ConcurrentHashMap<>();

    static {
        // 初始化配置
        OBJECT_MAPPER
                .registerModule(new JavaTimeModule()) // 支持LocalDateTime等Java8时间类型
                .setSerializationInclusion(JsonInclude.Include.NON_NULL) // 忽略null字段
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) // 忽略未知字段
                .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 允许空对象
    }

    @Override
    public <T> byte[] serialize(T obj) throws IOException {
        try {
            return OBJECT_MAPPER.writeValueAsBytes(obj);
        } catch (JsonProcessingException e) {
            throw new IOException("序列化失败 [类型: " + obj.getClass().getName() + "]", e);
        }
    }

    @Override
    public <T> T deserialize(byte[] bytes, Class<T> classType) throws IOException {
        return deserialize(bytes, classType, null);
    }

    /**
     * 支持泛型的反序列化方法
     * @param bytes 字节数组
     * @param classType 原始类型（如List.class）
     * @param genericType 泛型类型（如User.class）
     */
    public <T> T deserialize(byte[] bytes, Class<T> classType, Type genericType) throws IOException {
        try {
            JavaType javaType = buildJavaType(classType, genericType);
            T obj = OBJECT_MAPPER.readValue(bytes, javaType);

            // 处理RPC特殊类型
            if (obj instanceof RpcRequest) {
                return handleRequest((RpcRequest) obj, classType);
            } else if (obj instanceof RpcResponse) {
                return handleResponse((RpcResponse) obj, classType);
            }
            return obj;
        } catch (Exception e) {
            throw new IOException("反序列化失败 [类型: " + classType.getName() + "]", e);
        }
    }

    /**
     * 构建JavaType（处理泛型）
     */
    private JavaType buildJavaType(Class<?> rawType, Type genericType) {
        if (genericType == null) {
            return TypeFactory.defaultInstance().constructType(rawType);
        }
        return TYPE_CACHE.computeIfAbsent(genericType, type ->
                OBJECT_MAPPER.getTypeFactory().constructType(type)
        );
    }

    /**
     * 处理RPC请求的类型擦除问题（同原handleRequest方法）
     */
    private <T> T handleRequest(RpcRequest rpcRequest, Class<T> type) throws IOException {
        Class<?>[] parameterTypes = rpcRequest.getParameterTypes();
        Object[] args = rpcRequest.getArgs();

        for (int i = 0; i < parameterTypes.length; i++) {
            if (args[i] != null && !parameterTypes[i].isAssignableFrom(args[i].getClass())) {
                byte[] argBytes = OBJECT_MAPPER.writeValueAsBytes(args[i]);
                args[i] = OBJECT_MAPPER.readValue(argBytes, parameterTypes[i]);
            }
        }
        return type.cast(rpcRequest);
    }

    /**
     * 处理RPC响应的类型擦除问题（同原handleResponse方法）
     */
    private <T> T handleResponse(RpcResponse rpcResponse, Class<T> type) throws IOException {
        if (rpcResponse.getData() != null) {
            byte[] dataBytes = OBJECT_MAPPER.writeValueAsBytes(rpcResponse.getData());
            rpcResponse.setData(OBJECT_MAPPER.readValue(dataBytes, rpcResponse.getDataType()));
        }
        return type.cast(rpcResponse);
    }

    /**
     * 快捷方法：通过TypeReference处理复杂泛型
     * 示例：deserialize(bytes, new TypeReference<List<User>>() {})
     */
    public <T> T deserialize(byte[] bytes, TypeReference<T> typeReference) throws IOException {
        try {
            return OBJECT_MAPPER.readValue(bytes, typeReference);
        } catch (Exception e) {
            throw new IOException("反序列化失败 [TypeReference: " + typeReference.getType() + "]", e);
        }
    }
}
